/**
 * 
 */
package com.db.stockexchange.server;

import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.logging.Logger;

import com.db.stockexchange.server.orderbook.Deal;
import com.db.stockexchange.server.orderbook.IllegalOrderException;
import com.db.stockexchange.server.orderbook.Order;
import com.db.stockexchange.server.orderbook.OrderBook;

/**
 * @author Rayman
 * Represents logic of stock exchange 
 */
public class StockExchangeEngine {
	private static final String KEY_PARTIAL_FILL = "partial_fill";
	private static final String KEY_TICKERS = "tickers";
	
	HashMap<String, OrderBook> books = new HashMap<>();
	MessageHandler handler;
	Logger logger;
	
	public StockExchangeEngine(MessageHandler handler, Properties properites) {
		this.handler = handler;
		this.handler.setStockExchange(this);
		logger = Logger.getLogger(this.getClass().getName());
		String[] tickers = properites.getProperty(KEY_TICKERS).split(",");
		createOrderBooks(tickers, Boolean.parseBoolean(properites.getProperty(KEY_PARTIAL_FILL)));
	}
	
	private void createOrderBooks(String[] tickers, boolean usePartialFill) {
		for (String ticker : tickers)
			books.put(ticker, new OrderBook(ticker, usePartialFill));
	}
	
	public boolean isTickerNameValid(String ticker)
	{
		return books.containsKey(ticker);
	}
	
	public void addNewOrder(Order order) {
		String ticker = order.getTickerName();
		OrderBook book = books.get(ticker);
		if (book != null) {
			try {
				List<Deal> deals = book.addOrder(order);
				for (Deal deal : deals) {
					logger.fine(String.format("Occurred deal <%s>", deal.toString()));
					handler.sendExecReport(deal);
				}
			} catch (IllegalOrderException e) {
				logger.warning(e.getMessage());
				handler.sendReject(order, e.getMessage());
			}
		}
	}
	
	public void close() {
		for (Entry<String, OrderBook> item : books.entrySet())
			item.getValue().dispose();
		
		books.clear();
		handler.close();
	}
}
